﻿using Alternet.Common;
using Infragistics.Win.UltraWinMaskedEdit;
using OrBitDataModule.Base;
using OrBitDataModule.Common;
using OrBitDataModule.Contract;
using OrBitDataModule.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace OrBitDataModule
{
    public class TaskService
    {
        //private static TaskService _instance;

        public List<TaskModel> TaskList { get; set; }

        /// <summary>
        /// 消息事件
        /// </summary>
        public event EventHandler<string> OnMessage;
        /// <summary>
        /// 任务状态改变事件
        /// </summary>
        public event EventHandler<TaskEventArgs> OnTaskStatusChange;

        public TaskService()
        {
            TaskList = new List<TaskModel>();
        }

        /// <summary>
        /// 获取所有任务
        /// </summary>
        /// <returns></returns>
        public async Task<List<TaskModel>> InitAllTask()
        {
            TaskList.Clear();
            var result = await TaskApi.GetAllTaskAsync();
            if (result.Protocol != null)
            {
                foreach (var item in result.Protocol.Data)
                {
                    if (!TaskList.Any(a => a.UniqueId.Equals(item.DataProtocolId)))
                    {
                        TaskList.Add
                       (
                           new TaskModel()
                           {
                               UniqueId = item.DataProtocolId,
                               Status = TaskRunningStatus.Stoped,
                               TaskName = item.ProtocolName,
                               TaskType = item.ProtocolType,
                               ProtocolSetting = item.ProtocolSetting,
                               DataProtocolScriptId = item.DataProtocolScriptId,
                               ScriptName = item.ScriptName,
                               ApiName = item.ApiName,
                               ApiUserName = item.ApiUserName,
                               ApiPassword = item.ApiPassword,
                               DataTask = null
                           }
                        );
                    }
                }
            }
            return TaskList;
        }


        /// <summary>
        /// 开始任务
        /// </summary>
        /// <param name="uniqueId"></param>
        public async void StartTask(string uniqueId)
        {
            try
            {
                TaskModel taskModel = TaskList.FirstOrDefault(x => x.UniqueId == uniqueId);
                if (taskModel == null)
                {
                    OnMessage?.Invoke(this, $"启动任务失败！未能获取到任务");
                    return;
                }
                if (taskModel?.Status == TaskRunningStatus.Started || taskModel.Status == TaskRunningStatus.Starting)
                {
                    OnMessage?.Invoke(this, $"任务正在启动中或者已经启动");
                    return;
                }
                if (taskModel.DataTask == null)
                {
                    DataTaskBase dataTask = ProtocolUtils.CreatProtocol("OrBitDataModule.Protocol", taskModel.TaskType, taskModel.UniqueId, taskModel.DataProtocolScriptId, taskModel.ProtocolSetting, taskModel.TaskName, taskModel.ApiName, taskModel.ApiUserName, taskModel.ApiPassword);
                    taskModel.DataTask = dataTask;
                }
                OnTaskStatusChange?.Invoke(taskModel, new TaskEventArgs(taskModel.DataTask.UniqueId, TaskRunningStatus.Starting));
                taskModel.DataTask.OnStateChange += DataTask_OnStateChange;
                await Task.Run(() =>
                {
                    taskModel.DataTask.OnLoad();
                    taskModel.DataTask.OnLogEvent += DataTask_OnLogEvent;
                    taskModel.DataTask.Start();
                });
            }
            catch (Exception ex)
            {
                OnMessage?.Invoke(null, ex.Message);
            }
        }

        private void DataTask_OnStateChange(object sender, TaskEventArgs e)
        {
            SetTaskStatus(e.UniqueId, e.Status);
            OnTaskStatusChange?.Invoke(sender, e);
        }

        /// <summary>
        /// 停止任务
        /// </summary>
        /// <param name="uniqueId"></param>
        public void StopTask(string uniqueId)
        {
            TaskModel taskModel = TaskList.FirstOrDefault(x => x.UniqueId == uniqueId);
            if (taskModel != null)
            {
                taskModel.DataTask?.Stop();
                taskModel.DataTask.OnLogEvent -= DataTask_OnLogEvent;

                //销毁
                taskModel.DataTask.Context.Scheduler?.Shutdown();
                taskModel.DataTask.OnStateChange -= DataTask_OnStateChange;
                taskModel.DataTask?.OnDispose();
                taskModel.DataTask = null;
                GC.Collect();
            }
        }

        /// <summary>
        /// 销毁任务
        /// </summary>
        public void DisposeTask(string uniqueId)
        {
            TaskModel taskModel = TaskList.FirstOrDefault(x => x.UniqueId == uniqueId);
            if (taskModel != null)
            {
                taskModel.DataTask?.Stop();
                taskModel.DataTask.OnStateChange -= DataTask_OnStateChange;
                taskModel.DataTask.OnLogEvent -= DataTask_OnLogEvent;
                taskModel.DataTask?.OnDispose();
                taskModel.DataTask = null;
                GC.Collect();
            }
        }


        /// <summary>
        /// 获取任务对象
        /// </summary>
        /// <param name="uniqueId"></param>
        /// <returns></returns>
        public TaskModel GetTaskModel(string uniqueId)
        {
            TaskModel taskModel = TaskList.FirstOrDefault(x => x.UniqueId == uniqueId);
            if (taskModel != null && taskModel.DataTask == null)
            {
                DataTaskBase dataTask = ProtocolUtils.CreatProtocol("OrBitDataModule.Protocol", taskModel.TaskType, taskModel.UniqueId, taskModel.DataProtocolScriptId, taskModel.ProtocolSetting, taskModel.TaskName, taskModel.ApiName, taskModel.ApiUserName, taskModel.ApiPassword);
                taskModel.DataTask = dataTask;
            }
            return taskModel;
        }

        /// <summary>
        /// 获取任务对象
        /// </summary>
        /// <param name="uniqueId"></param>
        /// <returns></returns>
        public TaskModel GetTaskModelByName(string taskName) => TaskList.FirstOrDefault(x => x.TaskName == taskName);

        /// <summary>
        /// 获取任务对象
        /// </summary>
        /// <param name="uniqueId"></param>
        /// <returns></returns>
        public TaskModel GetTaskModel(List<TaskModel> list, string uniqueId)
        {
            TaskModel taskModel = list.FirstOrDefault(x => x.UniqueId == uniqueId);
            if (taskModel != null && taskModel.DataTask == null)
            {
                DataTaskBase dataTask = ProtocolUtils.CreatProtocol("OrBitDataModule.Protocol", taskModel.TaskType, taskModel.UniqueId, taskModel.DataProtocolScriptId, taskModel.ProtocolSetting, taskModel.TaskName, taskModel.ApiName, taskModel.ApiUserName, taskModel.ApiPassword);
                taskModel.DataTask = dataTask;
            }
            return taskModel;
        }


        /// <summary>
        /// 添加一个任务
        /// </summary>
        /// <param name="uniqueId"></param>
        /// <param name="taskModel"></param>
        public async Task<(bool Result, string Message)> DeleteTask(string uniqueId)
        {
            var result = await TaskApi.RemoveTask(uniqueId);
            if (result.Result)
            {
                if (TaskList.Any(t => t.UniqueId.Equals(uniqueId)))
                {
                    this.TaskList.Remove(TaskList.FirstOrDefault(t => t.UniqueId.Equals(uniqueId)));
                }
            }
            return result;
        }

        /// <summary>
        /// 停止所有任务
        /// </summary>
        public void StopAllTask() => TaskList.Where(t => t.Status == TaskRunningStatus.Started || t.Status == TaskRunningStatus.Starting).ToList().ForEach(x => { x.DataTask?.Stop(); x.DataTask?.OnDispose(); });


        /// <summary>
        /// 设置任务状态
        /// </summary>
        /// <param name="uniqueId"></param>
        /// <param name="status"></param>
        private void SetTaskStatus(string uniqueId, TaskRunningStatus status) => TaskList.FirstOrDefault(t => t.UniqueId == uniqueId).Status = status;
        private void DataTask_OnLogEvent(object sender, string e)
        {
            OnMessage?.Invoke(sender, e);
        }

        /// <summary>
        /// 获取任务状态
        /// </summary>
        /// <param name="uniqueId"></param>
        /// <returns></returns>
        public TaskRunningStatus GetTaskStatus(string uniqueId)
        {
            TaskModel taskModel = TaskList.FirstOrDefault(t => t.UniqueId == uniqueId);
            return taskModel == null ? TaskRunningStatus.Stoped : taskModel.Status;
        }
    }
}
